package com.yic.module.system.service.code;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yic.module.system.convert.code.CodeRuleConvert;
import com.yic.module.system.dal.dataobject.code.CodeRuleDO;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import com.yic.module.system.controller.admin.code.vo.*;
import com.yic.module.system.dal.dataobject.code.CodeDO;
import com.yic.framework.common.pojo.PageResult;

import com.yic.module.system.convert.code.CodeConvert;
import com.yic.module.system.dal.mysql.code.CodeMapper;

import static com.yic.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yic.module.system.enums.ErrorCodeConstants.*;

/**
 * 编号规则 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
public class CodeServiceImpl implements CodeService {

    @Resource
    private CodeMapper codeMapper;
    @Resource
    private CodeRuleService codeRuleService;
    @Resource
    private TransactionTemplate transactionTemplate;

    @Override
    public Long createCode(CodeCreateReqVO createReqVO) {
        validateCreateOrUpdate(null, createReqVO.getName(), createReqVO.getCode());
        List<CodeRuleCreateReqVO> codeRuleCreateReqVOS = CodeRuleConvert.INSTANCE.convertList04(createReqVO.getRules());
        codeRuleService.validateCodeRule(codeRuleCreateReqVOS);
        CodeDO code = CodeConvert.INSTANCE.convert(createReqVO);
        // 插入
        transactionTemplate.execute(status -> {
            codeMapper.insert(code);
            for (int i = 0; i < codeRuleCreateReqVOS.size(); i++) {
                CodeRuleCreateReqVO reqVO = codeRuleCreateReqVOS.get(i);
                reqVO.setCodeId(code.getId());
                reqVO.setSerial(i+1);
            }
            codeRuleService.batchCreateCodeRule(codeRuleCreateReqVOS);
            return Boolean.TRUE;
        });
        // 返回
        return code.getId();
    }

    @Override
    public void updateCode(CodeUpdateReqVO updateReqVO) {
        validateCreateOrUpdate(updateReqVO.getId(), updateReqVO.getName(), updateReqVO.getCode());
        List<CodeRuleCreateReqVO> codeRuleCreateReqVOS = CodeRuleConvert.INSTANCE.convertList06(updateReqVO.getRules());
        codeRuleService.validateCodeRule(codeRuleCreateReqVOS);
        // 更新
        CodeDO updateObj = CodeConvert.INSTANCE.convert(updateReqVO);
        transactionTemplate.execute(status -> {
            codeMapper.updateById(updateObj);
            codeRuleService.deleteCodeRuleByCodeId(updateObj.getId());
            for (int i = 0; i < codeRuleCreateReqVOS.size(); i++) {
                CodeRuleCreateReqVO reqVO = codeRuleCreateReqVOS.get(i);
                reqVO.setCodeId(updateObj.getId());
                reqVO.setSerial(i+1);
            }
            codeRuleService.batchCreateCodeRule(codeRuleCreateReqVOS);
            return Boolean.TRUE;
        });

    }

    @Override
    public void deleteCode(Long id) {
        // 校验存在
        validateCodeExists(id);
        // 删除
        codeMapper.deleteById(id);
    }

    private void validateCreateOrUpdate(Long id, String name, String code){
        validateRuleNameExists(id, name);
        validateRuleCodeExists(id, code);

    }

    private void validateRuleCodeExists(Long id, String code){
        CodeDO codeDO = codeMapper.selectByCode(code);
        if (ObjectUtil.isEmpty(codeDO)){
            return;
        }
        if (id == null){
            throw exception(CODE_CODE_EXISTS);
        }
        if (!id.equals(codeDO.getId())){
            throw exception(CODE_CODE_EXISTS);
        }
    }

    private void validateRuleNameExists(Long id, String name){
        CodeDO codeDO = codeMapper.selectByName(name);
        if (ObjectUtil.isEmpty(codeDO)){
            return;
        }
        if (id == null){
            throw exception(CODE_NAME_EXISTS);
        }
        if (!id.equals(codeDO.getId())){
            throw exception(CODE_NAME_EXISTS);
        }
    }

    private void validateCodeExists(Long id) {
        if (codeMapper.selectById(id) == null) {
            throw exception(CODE_NOT_EXISTS);
        }
    }

    @Override
    public CodeDO getCode(Long id) {
        return codeMapper.selectById(id);
    }

    @Override
    public List<CodeDO> getCodeList(Collection<Long> ids) {
        return codeMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<CodeDO> getCodePage(CodePageReqVO pageReqVO) {
        return codeMapper.selectPage(pageReqVO);
    }

    @Override
    public List<CodeDO> getCodeList(CodeExportReqVO exportReqVO) {
        return codeMapper.selectList(exportReqVO);
    }

    @Override
    public String genCode(String code) {
        /** 临时毫秒数生成*/
        return IdUtil.getSnowflakeNextIdStr();
    }

}
